#pragma once
#include <vector>
#include <iostream>

using namespace std;

struct Mine
{
	bool IsMark;
	bool IsMine;
	int RoundMineNum;
};

int offset[8][2] = { 
	{0, -1},
	{-1, -1},
	{-1, 0},
	{-1, 1},
	{0, 1},
	{1, 1},
	{1, 0},
	{1, -1},
};

class MarkMine
{
public:
	MarkMine(int m, int n, int mine)
	{
		this->m = m;
		this->n = n;
		for (int i = 0; i < m; ++i)
		{
			data.push_back(vector<Mine>());
			for (int j = 0; j < n; ++j)
			{
				Mine m;
				m.IsMark = false;
				m.IsMine = false;
				m.RoundMineNum = 0;
				data[i].push_back(m);
			}
		}

		for (int i = 0; i < mine; ++i)
		{
			int x = rand() % m;
			int y = rand() % n;
			cout << "rand mine is " << x << ", " << y << endl;
			Mine& mine = data[x][y];
			mine.IsMine = true;
		}

		CalcRoundMineNum();
	}

	void CalcRoundMineNum()
	{
		for (int i = 0; i < m; ++i)
		{
			for (int j = 0; j < n; ++j)
			{
				int num = 0;
				for (int k = 0; k < sizeof(offset) / sizeof(offset[0]); ++k)
				{
					int x = i + offset[k][0];
					int y = j + offset[k][1];
					if (!IsValid(x, y))
					{
						continue;
					}
					if (data[x][y].IsMine)
					{
						num++;
					}
				}
				data[i][j].RoundMineNum = num;
			}
		}
	}

	bool IsValid(int x, int y)
	{
		return x >= 0 && x < m && y >= 0 && y < n;
	}

	void Mark(int x, int y)
	{
		if (data[x][y].IsMine)
		{
			cout << "Sorry, you are die!" << endl;
			return;
		}
		DoMark(x, y);
	}

	void DoMark(int x, int y)
	{
		if (!IsValid(x, y))
		{
			return;
		}

		if (data[x][y].IsMark)
		{
			return;
		}
		if (data[x][y].IsMine)
		{
			return;
		}
		data[x][y].IsMark = true;

		for (int i = 0; i < sizeof(offset) / sizeof(offset[0]); ++i)
		{
			int newX = x + offset[i][0];
			int newY = y + offset[i][1];
			if (!IsValid(newX, newY))
			{
				continue;
			}
			DoMark(newX, newY);
		}
	}

	void Show()
	{
		cout << "Mark Mine:" << endl;
		for (int i = 0; i < m; ++i)
		{
			for (int j = 0; j < n; ++j)
			{
				char c = ' ';
				if (!data[i][j].IsMark)
				{
					c = '*';
				}
				else if (data[i][j].IsMine)
				{
					c = '.';
				}
				else
				{
					c = '0' + data[i][j].RoundMineNum;
				}
				cout << c << " ";
			}
			cout << endl;
		}
	}

private:
	int m;
	int n;
	vector<vector<Mine>> data;
};